package fp.poczadly.client.presenter;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.cellview.client.AbstractHasData;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;

import fp.poczadly.client.LiveChatServiceAsync;
import fp.poczadly.client.event.LoginEvent;
import fp.poczadly.shared.Message;
import fp.poczadly.shared.User;
import fp.poczadly.shared.Utils;


public class PrivateMessagePresenter implements Presenter {

	public interface Display {
		public HasText userLabel();
		public AbstractHasData<String> messageList();
		public HasValue<String> messageTextField();
		public HasClickHandlers sendButton();
		public HasClickHandlers closeButton();
		
		Widget asWidget();
	}

	private final LiveChatServiceAsync rpcService;
	private HandlerManager eventBus;
	private Display display;
	
	private User fromUser;
	private User toUser;
	
	private List<String> messageList = new ArrayList<String>();
	
	public PrivateMessagePresenter( LiveChatServiceAsync rpcService, HandlerManager eventBus, User fromUser, Display display ) {
		this.rpcService = rpcService;
		this.eventBus = eventBus;
		this.fromUser = fromUser;
		this.display = display;
	}
	
	public void bind() {
		ChatPresenter.setPrivMessage( true );
		
		display.sendButton().addClickHandler( new ClickHandler() {
			
			@Override
			public void onClick( ClickEvent event ) {
				sendMessage();
			}
		} );
		
		display.closeButton().addClickHandler( new ClickHandler() {
			
			@Override
			public void onClick( ClickEvent event ) {
				rpcService.checkSession( Utils.USER, new AsyncCallback<User>() {

					@Override
					public void onFailure( Throwable caught ) {
						eventBus.fireEvent( null );
						ChatPresenter.setPrivMessage( false );
					}

					@Override
					public void onSuccess( User result ) {
						eventBus.fireEvent( new LoginEvent( result ) );
						rpcService.removePrivateMessages( result, new AsyncCallback<Void>() {

							@Override
							public void onFailure( Throwable caught ) {}

							@Override
							public void onSuccess( Void result ) {}
						} );
					}
				
				} );
			}
		} );
		
		addTimer();
	}
	
	public void addTimer() {
		Timer timer = new Timer() {
			
			@Override
			public void run() {
				if( receiveMessages() != null )
					display.messageList().setRowData( 0, receiveMessages() );
			}
		};
		
		timer.scheduleRepeating( Utils.SCHEDULE_TIME );
	}
	
	@Override
	public void go( HasWidgets container ) {
		bind();
		
		container.clear();
		container.add( display.asWidget() );
	}
	
	public void sendMessage() {
		Message message = new Message( fromUser, toUser, display.messageTextField().getValue() );

		rpcService.sendMessage( message, new AsyncCallback<Void>() {

			@Override
			public void onSuccess( Void result ) {}

			@Override
			public void onFailure( Throwable caught ) {
				Window.alert( Utils.CANNOT_SEND_MESSAGE );
			}
		} );
		
		display.messageTextField().setValue( "" );
	}
	
	public List<String> receiveMessages() {
		rpcService.receivePrivateMessages( fromUser, new AsyncCallback<List<Message>>() {

			@Override
			public void onFailure( Throwable caught ) {
				Window.alert( Utils.CANNOT_RECEIVE_MESSAGES );
			}

			@Override
			public void onSuccess( List<Message> result ) {
				messageList.clear();
				
				for( Message message : result ) {
					String body = message.getBody();
					
					messageList.add( body );
				}
			}
		} );
		
		return messageList;
	}
	
	public void setToUser( User user ) {
		this.toUser = user;
	}
	
	public void setFromUser( User user ) {
		this.fromUser = user;
	}
	
}
